require(tidyverse)
Loading required package: tidyverse
── Attaching core tidyverse packages ─────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.2     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.2     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.1     
── Conflicts ───────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
require(flowCore)
Loading required package: flowCore
require(flowClust)
Loading required package: flowClust

Attaching package: ‘flowClust’

The following object is masked from ‘package:graphics’:

    box

The following object is masked from ‘package:base’:

    Map
require(openCyto)
Loading required package: openCyto
require(ggcyto)
Loading required package: ggcyto
Loading required package: ncdfFlow
Loading required package: BH
Loading required package: flowWorkspace
As part of improvements to flowWorkspace, some behavior of
GatingSet objects has changed. For details, please read the section
titled "The cytoframe and cytoset classes" in the package vignette:

  vignette("flowWorkspace-Introduction", "flowWorkspace")
require(cowplot)
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:lubridate’:

    stamp
require(ggrdiges)
Loading required package: ggrdiges
Warning in library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
  there is no package called ‘ggrdiges’
old <- theme_set(theme_minimal())

Background

We previously observed a “dead-like” population in mock-treated samples, and also an unstained population in 10 mM H2O2-treated cells. Here, we explore different staining buffer compositions and monitor those two behaviors.

Data

This is the flow cytometry data for mig-log phase C. glabrata cells stained with PI/SYTO9/PI+SYTO9 in different staining buffers, and run through flow cytometry (details in ELN).

Import data

FCS files are stored in RDSS/user/flow cytometry, FCS is read and write into an input tsv table. The tsv file is avaliable from the Input folder.

# use relative path to make it easier for collaboration
data.path = "../../../00-Shared/02-data/02.01-flow-cytometry/20240108-extended-buffer-optimization/"
dat.f1e <- read.flowSet(path = data.path,
                        transformation = FALSE,        # the original values are already linearized. 
                        emptyValue = FALSE,
                        alter.names = TRUE,            # change parameter names to R format
                        column.pattern = ".H|FSC|SSC") # only load the height variables for the fluorescent parameters

Simplify the sample names

Gatting strategies

The following gaphing steps are used to gate singlets by FSC and SSC values. Only singlets are included in analysis.

Gate for singlets

Gate for outlier

outlier.gate <- rectangleGate(filterId = "-outlier", "FSC.H" = c(1.2e5, 1e6), "SSC.H" = c(1e2, 1e6))
ggcyto(dat[13], aes(x = FSC.H, y = SSC.H), subset = "root") +
  geom_hex(bins = 64) + geom_gate(outlier.gate) + facet_wrap(~name, ncol = 2) + ggcyto_par_set(limits = "instrument")
Coordinate system already present. Adding new coordinate system, which will replace the existing
one.

Add gate to GS

# create a GatingSet
gs <- GatingSet(dat)
# add root gate
gs_pop_add(gs, outlier.gate, parent = "root")
[1] 2
recompute(gs)
done!

Gate for singlets

scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(30,300)))
ex <- Subset(dat[c(5, 15)], outlier.gate)
polygon <- matrix(c(1e5, 1e5, 1e6, 1e6, 
                    60, 105, 135,60), ncol = 2)
colnames(polygon) <- c("FSC.H", "FSC.W")
singlet.gate <- polygonGate(filterId = "singlet", .gate = polygon)
ggcyto(ex, aes(x = FSC.H, y = FSC.W)) + geom_hex(bins = 128) + geom_gate(singlet.gate) + geom_stats() + scPars
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Add this gate to the gatingSet

gs_pop_add(gs, singlet.gate, parent = "-outlier", name = "singlet")
[1] 3
recompute(gs)
done!

Gate for the unstained population

Unstained population is defined as population below 10^2 in both channels (in the noise range).

#scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(0,1e6)))
select <- c(7,19)
ex <- Subset(dat[select], singlet.gate)
polygon2 <- matrix(c(0, 1e2, 1e2, 0,
                    0, 0, 1e2, 1e2), ncol = 2)
colnames(polygon2) <- c("BL1.H", "BL3.H")
unstained.gate <- polygonGate(filterId = "unstained", .gate = polygon2)
ggcyto(ex, aes(x = BL1.H, y = BL3.H)) +
  geom_hex(bins = 64) +
  geom_gate(unstained.gate) + geom_stats() +# scPars +
  scale_x_logicle() + scale_y_logicle() 

Add this gate to the gatingSet

Gate for the dead-like population

Dead population is defined based on 1M treated sample.

#scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(0,1e6)))
select <- c(19,22)
ex <- Subset(dat[select], singlet.gate)
#polygon <- matrix(c(10^3, 10^2.5,10^3, 10^5,
#                    10^4.5, 10^2.2, 10^2.2, 10^4), ncol = 2)
polygon <- matrix(c(10^2, 10^3, 10^4.5, 10^2.5,
                    10^2.3, 10^2.3, 10^4, 10^4), ncol = 2)
colnames(polygon) <- c("BL1.H", "BL3.H")
dead.gate <- polygonGate(filterId = "dead_like", .gate = polygon)
ggcyto(ex, aes(x = BL1.H, y = BL3.H)) +
  geom_hex(bins = 64) +
  geom_gate(dead.gate) + geom_stats() + #scPars +
  scale_x_logicle() + scale_y_logicle() 

Add this gate to the gatingSet

Analysis & Plots

Visualize one set of data

With gates

subset.to.plot <- with(pData(gs), dye == "Both" & date == '2024-01-09')
p <- ggcyto(gs[subset.to.plot],
            aes(x = BL1.H, y = BL3.H), subset = "singlet") + 
  geom_hex(aes(fill = after_stat(density)), bins = 64) + 
  geom_gate("dead_like", linewidth = 0.5, alpha = 0.5) +
  geom_stats(type = "percent", location = "gate", adjust = c(0, 1),
             digits = 1, size = 3) +
  geom_gate("unstained", linewidth = 0.5, alpha = 0.5) +
  geom_stats(type = "percent", location = "data", adjust = c(0.2, 0.003),
             digits = 1, size = 3) +
  facet_grid(buffer ~ treatment,
             labeller = as_labeller(c(tr.levels, bu.levels), multi_line = F)) +
  scale_x_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  scale_y_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  theme_minimal(base_size = 14) + 
  panel_border(color = "gray20") + #background_grid(major = "none", minor = "none") +
  theme(
    #axis.line = element_blank(),
    strip.text.y = element_text(face = 2),
    strip.text.x = element_text(face = 2),
    axis.text = element_text(size = rel(0.6)),
    plot.title = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
  )
print(p)
ggsave("../output/fig2-compare-staining-buffers-with-gate-20240923.png", width = 5, height = 5)

Without gates

subset.to.plot <- with(pData(gs), dye == "Both" & date == '2024-01-09')
p <- ggcyto(gs[subset.to.plot],
            aes(x = BL1.H, y = BL3.H), subset = "singlet") + 
  geom_hex(aes(fill = after_stat(density)), bins = 64) + 
  facet_grid(buffer ~ treatment,
             labeller = as_labeller(c(tr.levels, bu.levels), multi_line = F)) +
  scale_x_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  scale_y_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  theme_minimal(base_size = 14) + 
  panel_border(color = "gray20") + #background_grid(major = "none", minor = "none") +
  theme(
    #axis.line = element_blank(),
    strip.text.y = element_text(face = 2),
    strip.text.x = element_text(face = 2),
    axis.text = element_text(size = rel(0.6)),
    plot.title = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
  )
print(p)
ggsave("../output/fig2-compare-staining-buffers-no-gate-20240923.png", width = 5, height = 5)

Export gated event counts

tmp <- gs_pop_get_stats(gs) %>% 
  mutate(pop = gsub(".*/", "", pop), pop = gsub("-outlier", "cells", pop)) %>% 
  pivot_wider(names_from = pop, names_prefix = "n_", values_from = count) %>% 
  mutate(
    pc_dead_like = num(n_dead_like / n_singlet, label = "%", scale = 100),
    pc_unstained = num(n_unstained / n_singlet, label = "%", scale = 100)
  )

gated_stats <- left_join(
  as_tibble(pData(gs)),
  tmp,
  by = c("name" = "sample")
) %>% dplyr::filter(dye == "Both") %>% select(-dye)
  
print(gated_stats)
write_tsv(gated_stats, file = "../output/fig2-compare-staining-buffer-gated-stats.tsv")

Plot percentages

We will primarily look at the mock sample, as the purpose of the buffer comparison is to find a buffer that will minimize the dead-like and unstained populations.

p1 <- gated_stats %>% 
  # plot the mock sample only
  dplyr::filter(treatment == "0") %>% 
  pivot_longer(
    cols = starts_with("pc_"),
    names_to = "var",
    values_to = "value"
  ) %>% 
  ggplot(aes(x = buffer, y = value))  + 
  geom_bar(stat = "summary", fun = "mean", fill = "gray80") +
  geom_point(size = 3, position = position_jitter(0.05)) + 
  scale_y_continuous(labels = scales::percent_format()) +
  scale_x_discrete(labels = bu.levels) +
  facet_wrap(~var, nrow = 2, scales = "free_y", labeller = as_labeller(
    c("pc_dead_like" = "% Dead-like", "pc_unstained" = "% Unstained"))) +
  labs(x = NULL, y = "Population frequency") +
  theme_minimal(base_size = 18) + panel_border(color = "gray20") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        strip.text = element_text(color = "steelblue", face = 2))
print(p1 + facet_wrap(~var, ncol = 2, scales = "free_y", labeller = as_labeller(
    c("pc_dead_like" = "% Dead-like", "pc_unstained" = "% Unstained"))))
ggsave(filename = "../output/fig2bc-compare-buffer-plot-stats.png", 
       plot = p1, width = 4, height = 7)

Sample-to-sample variation

Visaulize sample-to-sample variability in mock-treated cells across three replicates

subset.to.plot <- with(pData(gs), dye == "Both" & treatment == "0")
date.levels = paste("Replicate", 1:3); names(date.levels) = unique(sample$date)
p <- ggcyto(gs[subset.to.plot],
            aes(x = BL1.H, y = BL3.H), subset = "singlet") + 
  geom_hex(aes(fill = after_stat(density)), bins = 64) + 
  facet_grid(date~buffer, labeller = as_labeller(c(date.levels, bu.levels), 
                                                   multi_line = F)) +
  scale_x_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  scale_y_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  theme_minimal(base_size = 14) + 
  panel_border(color = "gray20") + #background_grid(major = "none", minor = "none") +
  theme(
    #axis.line = element_blank(),
    strip.text.y = element_text(face = 2),
    strip.text.x = element_text(face = 2),
    axis.text = element_text(size = rel(0.6)),
    plot.title = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
  )
print(p)

Supplementary plots

PI-alone

subset.to.plot <- with(pData(gs), dye == "PI" & date == '2024-01-09')
p <- ggcyto(gs[subset.to.plot],
            aes(x = BL1.H, y = BL3.H), subset = "singlet") + 
  geom_hex(aes(fill = after_stat(density)), bins = 64) + 
  facet_grid(buffer ~ treatment,
             labeller = as_labeller(c(tr.levels, bu.levels), multi_line = F)) +
  scale_x_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  scale_y_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  theme_minimal(base_size = 14) + 
  panel_border(color = "gray20") + #background_grid(major = "none", minor = "none") +
  theme(
    #axis.line = element_blank(),
    strip.text.y = element_text(face = 2),
    strip.text.x = element_text(face = 2),
    axis.text = element_text(size = rel(0.6)),
    plot.title = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
  )
print(p)
ggsave("../output/fig2sup-compare-staining-buffers-PI-only-20240923.png", width = 5, height = 5)

SYTO9 alone

subset.to.plot <- with(pData(gs), dye == "SYTO9" & date == '2024-01-09')
p <- ggcyto(gs[subset.to.plot],
            aes(x = BL1.H, y = BL3.H), subset = "singlet") + 
  geom_hex(aes(fill = after_stat(density)), bins = 128) + 
  facet_grid(buffer ~ treatment,
             labeller = as_labeller(c(tr.levels, bu.levels), multi_line = F)) +
  scale_x_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  scale_y_logicle(breaks = c(10^2, 10^3, 10^4)) + 
  theme_minimal(base_size = 14) + 
  panel_border(color = "gray20") + #background_grid(major = "none", minor = "none") +
  theme(
    #axis.line = element_blank(),
    strip.text.y = element_text(face = 2),
    strip.text.x = element_text(face = 2),
    axis.text = element_text(size = rel(0.6)),
    plot.title = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
  )
print(p)
ggsave("../output/fig2sup-compare-staining-buffers-SYTO9-only-20240923.png", width = 5, height = 5)

LS0tCnRpdGxlOiAiQnVmZmVyIE9wdGltaXphdGlvbiIKZGF0ZTogMjAyMy0xMi0xOCwgdXBkYXRlZCBgciBTeXMuRGF0ZSgpYAphdXRob3I6IEJpbiBaLiBIZSwgb3JpZ2luYWxseSBieSBIYW54aSBUYW5nCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgpgYGB7ciBzZXR1cCwgbWVzc2FnZT1GQUxTRX0KcmVxdWlyZSh0aWR5dmVyc2UpCnJlcXVpcmUoZmxvd0NvcmUpCnJlcXVpcmUoZmxvd0NsdXN0KQpyZXF1aXJlKG9wZW5DeXRvKQpyZXF1aXJlKGdnY3l0bykKcmVxdWlyZShjb3dwbG90KQpyZXF1aXJlKGdncmRpZ2VzKQpgYGAKCmBgYHtyfQpvbGQgPC0gdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSkKYGBgCgojIEJhY2tncm91bmQKV2UgcHJldmlvdXNseSBvYnNlcnZlZCBhICJkZWFkLWxpa2UiIHBvcHVsYXRpb24gaW4gbW9jay10cmVhdGVkIHNhbXBsZXMsIGFuZCBhbHNvIGFuIHVuc3RhaW5lZCBwb3B1bGF0aW9uIGluIDEwIG1NIEgyTzItdHJlYXRlZCBjZWxscy4gSGVyZSwgd2UgZXhwbG9yZSBkaWZmZXJlbnQgc3RhaW5pbmcgYnVmZmVyIGNvbXBvc2l0aW9ucyBhbmQgbW9uaXRvciB0aG9zZSB0d28gYmVoYXZpb3JzLgoKIVtdKC4uLy4uLzExIEluaXRpYWwgb2JzZXJ2YXRpb24vb3V0cHV0L2ZpZzEtc3RhaW5pbmctY29uc2lzdGVuY3ktZ2F0ZWQtMjAyNDA5MTMucG5nKQoKIyBEYXRhClRoaXMgaXMgdGhlIGZsb3cgY3l0b21ldHJ5IGRhdGEgZm9yIG1pZy1sb2cgcGhhc2UgX0MuIGdsYWJyYXRhXyBjZWxscyBzdGFpbmVkIHdpdGggUEkvU1lUTzkvUEkrU1lUTzkgaW4gZGlmZmVyZW50IHN0YWluaW5nIGJ1ZmZlcnMsIGFuZCBydW4gdGhyb3VnaCBmbG93IGN5dG9tZXRyeSAoZGV0YWlscyBpbiBFTE4pLgoKIyMgSW1wb3J0IGRhdGEKPiBGQ1MgZmlsZXMgYXJlIHN0b3JlZCBpbiBSRFNTL3VzZXIvZmxvdyBjeXRvbWV0cnksIEZDUyBpcyByZWFkIGFuZCB3cml0ZSBpbnRvIGFuIGlucHV0IHRzdiB0YWJsZS4gVGhlIHRzdiBmaWxlIGlzIGF2YWxpYWJsZSBmcm9tIHRoZSBJbnB1dCBmb2xkZXIuCgpgYGB7cn0KIyB1c2UgcmVsYXRpdmUgcGF0aCB0byBtYWtlIGl0IGVhc2llciBmb3IgY29sbGFib3JhdGlvbgpkYXRhLnBhdGggPSAiLi4vLi4vLi4vMDAtU2hhcmVkLzAyLWRhdGEvMDIuMDEtZmxvdy1jeXRvbWV0cnkvMjAyNDAxMDgtZXh0ZW5kZWQtYnVmZmVyLW9wdGltaXphdGlvbi8iCmRhdDAgPC0gcmVhZC5mbG93U2V0KHBhdGggPSBkYXRhLnBhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uID0gRkFMU0UsICAgICAgICAjIHRoZSBvcmlnaW5hbCB2YWx1ZXMgYXJlIGFscmVhZHkgbGluZWFyaXplZC4gCiAgICAgICAgICAgICAgICAgICAgICAgIGVtcHR5VmFsdWUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXIubmFtZXMgPSBUUlVFLCAgICAgICAgICAgICMgY2hhbmdlIHBhcmFtZXRlciBuYW1lcyB0byBSIGZvcm1hdAogICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4ucGF0dGVybiA9ICIuSHxGU0N8U1NDIikgIyBvbmx5IGxvYWQgdGhlIGhlaWdodCB2YXJpYWJsZXMgZm9yIHRoZSBmbHVvcmVzY2VudCBwYXJhbWV0ZXJzCmBgYAoKU2ltcGxpZnkgdGhlIHNhbXBsZSBuYW1lcwoKYGBge3J9CnNvdXJjZSgiLi4vLi4vLi4vMDAtU2hhcmVkLzAxLXNjcmlwdC8yMDIyMDMyNi1zaW1wbGlmeS1uYW1lcy1zdWJyb3V0aW5lLlIiKQpvcmlOYW1lcyA8LSBzYW1wbGVOYW1lcyhkYXQwKQpzaG9ydE5hbWVzIDwtIHNpbXBsaWZ5TmFtZXMob3JpTmFtZXMpOyBuYW1lcyhzaG9ydE5hbWVzKSA8LSBvcmlOYW1lcwp0bXAgPC0gc3RyX3NwbGl0KG9yaU5hbWVzLCBwYXR0ZXJuID0gIlsgX10rIiwgc2ltcGxpZnkgPSBUUlVFKVssYygxLCA2LCA3LCA4KV0gCmNvbG5hbWVzKHRtcCkgPC0gYygiZGF0ZSIsICJidWZmZXIiLCAidHJlYXRtZW50IiwgImR5ZSIpIApzYW1wbGUgPC0gZGF0YS5mcmFtZSh0bXApICU+JSAKICBtdXRhdGUoCiAgICBkYXRlID0gbWR5KGRhdGUpLAogICAgZHllID0gZmFjdG9yKGR5ZSwgbGV2ZWxzID0gYygicC5mY3MiLCAicy5mY3MiLCAiYi5mY3MiKSwgCiAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiUEkiLCAiU1lUTzkiLCAiQm90aCIpKSwKICAgICAgI2lmZWxzZShkeWUgPT0gInAuZmNzIiwgIlBJIiwgaWZlbHNlKER5ZSA9PSAicy5mY3MiLCAiU1lUTzkiLCAiQm90aCIpKSwKICAgIGJ1ZmZlciA9IGZhY3RvcihidWZmZXIsIGxldmVscyA9IGMoInciLCAic2EiLCAicGIiLCAic2MiKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJkZEgyTyIsICJTYWxpbmUiLCAiUEJTIiwgIlNEIG1lZGlhIikpLAogICAgICAjaWZlbHNlKEJ1ZmZlciA9PSAic2EiLCAiU2FsaW5lIiwgaWZlbHNlKEJ1ZmZlciA9PSAicGIiLCAiUEJTIiwgaWZlbHNlKEJ1ZmZlciA9PSAidyIsICJkZEgyTyIsICJzYyBjb21wbGV0ZSIpKSksCiAgICB0cmVhdG1lbnQgPSBmYWN0b3IodHJlYXRtZW50LCBsZXZlbHMgPSBjKDAsIDEwLCAxMDAsIDEwMDApKQogICkKIyBkZWZpbmUgbGV2ZWxzIHZlY3RvciBmb3IgcGxvdHRpbmcKdHIubGV2ZWxzID0gcGFzdGUobGV2ZWxzKHNhbXBsZSR0cmVhdG1lbnQpLCAibU0iLCBzZXAgPSAiICIpCnRyLmxldmVsc1s0XSA9ICIxTSIKbmFtZXModHIubGV2ZWxzKSA9IGxldmVscyhzYW1wbGUkdHJlYXRtZW50KQpidS5sZXZlbHMgPSBjKCJESSBXYXRlciIsICJTYWxpbmUiLCAiUEJTIiwgIlNEIG1lZGlhIikKbmFtZXMoYnUubGV2ZWxzKSA9IGxldmVscyhzYW1wbGUkYnVmZmVyKQojIGVuZCBkZWZpbmluZwojIGFzc2lnbiByb3duYW1lcyB0byB0aGUgc2FtcGxlIGRhdGEgZnJhbWUsIG5lY2Vzc2FyeSBmb3IgcERhdGEgYXNzaWdubWVudApyb3duYW1lcyhzYW1wbGUpIDwtIHNob3J0TmFtZXMKIyBtYWtlIGEgY29weSBvZiBkYXQwCmRhdCA8LSBkYXQwCmlmKGFsbChzYW1wbGVOYW1lcyhkYXQpID09IG9yaU5hbWVzKSl7CiAgc2FtcGxlTmFtZXMoZGF0KSA8LSBzaG9ydE5hbWVzCn0KcERhdGEoZGF0KSA8LSBzYW1wbGUKcHJpbnQocERhdGEoZGF0KSkKd3JpdGVfdHN2KHBEYXRhKGRhdCksIGZpbGUgPSAiLi4vaW5wdXQvMjAyNDA5MTYtZmlnLTItYnVmZmVyLW9wdGltaXplLXNhbXBsZS1pbmZvLnRzdiIpCmBgYAoKIyBHYXR0aW5nIHN0cmF0ZWdpZXMKPiBUaGUgZm9sbG93aW5nIGdhcGhpbmcgc3RlcHMgYXJlIHVzZWQgdG8gZ2F0ZSBzaW5nbGV0cyBieSBGU0MgYW5kIFNTQyB2YWx1ZXMuIE9ubHkgc2luZ2xldHMgYXJlIGluY2x1ZGVkIGluIGFuYWx5c2lzLgoKIyMgR2F0ZSBmb3Igc2luZ2xldHMKR2F0ZSBmb3Igb3V0bGllciAKCmBgYHtyfQpvdXRsaWVyLmdhdGUgPC0gcmVjdGFuZ2xlR2F0ZShmaWx0ZXJJZCA9ICItb3V0bGllciIsICJGU0MuSCIgPSBjKDEuMmU1LCAxZTYpLCAiU1NDLkgiID0gYygxZTIsIDFlNikpCmdnY3l0byhkYXRbMTNdLCBhZXMoeCA9IEZTQy5ILCB5ID0gU1NDLkgpLCBzdWJzZXQgPSAicm9vdCIpICsKICBnZW9tX2hleChiaW5zID0gNjQpICsgZ2VvbV9nYXRlKG91dGxpZXIuZ2F0ZSkgKyBmYWNldF93cmFwKH5uYW1lLCBuY29sID0gMikgKyBnZ2N5dG9fcGFyX3NldChsaW1pdHMgPSAiaW5zdHJ1bWVudCIpCmBgYApBZGQgZ2F0ZSB0byBHUwpgYGB7cn0KIyBjcmVhdGUgYSBHYXRpbmdTZXQKZ3MgPC0gR2F0aW5nU2V0KGRhdCkKIyBhZGQgcm9vdCBnYXRlCmdzX3BvcF9hZGQoZ3MsIG91dGxpZXIuZ2F0ZSwgcGFyZW50ID0gInJvb3QiKQpyZWNvbXB1dGUoZ3MpCmBgYAoKR2F0ZSBmb3Igc2luZ2xldHMKCmBgYHtyfQpzY1BhcnMgPC0gZ2djeXRvX3Bhcl9zZXQobGltaXRzID0gbGlzdCh4ID0gYygwLDFlNiksIHkgPSBjKDMwLDMwMCkpKQpleCA8LSBTdWJzZXQoZGF0W2MoNSwgMTUpXSwgb3V0bGllci5nYXRlKQpwb2x5Z29uIDwtIG1hdHJpeChjKDFlNSwgMWU1LCAxZTYsIDFlNiwgCiAgICAgICAgICAgICAgICAgICAgNjAsIDEwNSwgMTM1LDYwKSwgbmNvbCA9IDIpCmNvbG5hbWVzKHBvbHlnb24pIDwtIGMoIkZTQy5IIiwgIkZTQy5XIikKc2luZ2xldC5nYXRlIDwtIHBvbHlnb25HYXRlKGZpbHRlcklkID0gInNpbmdsZXQiLCAuZ2F0ZSA9IHBvbHlnb24pCmdnY3l0byhleCwgYWVzKHggPSBGU0MuSCwgeSA9IEZTQy5XKSkgKyBnZW9tX2hleChiaW5zID0gMTI4KSArIGdlb21fZ2F0ZShzaW5nbGV0LmdhdGUpICsgZ2VvbV9zdGF0cygpICsgc2NQYXJzCmBgYAoKCkFkZCB0aGlzIGdhdGUgdG8gdGhlIGdhdGluZ1NldApgYGB7cn0KZ3NfcG9wX2FkZChncywgc2luZ2xldC5nYXRlLCBwYXJlbnQgPSAiLW91dGxpZXIiLCBuYW1lID0gInNpbmdsZXQiKQpyZWNvbXB1dGUoZ3MpCmBgYAoKIyMgR2F0ZSBmb3IgdGhlIHVuc3RhaW5lZCBwb3B1bGF0aW9uCgo+IFVuc3RhaW5lZCBwb3B1bGF0aW9uIGlzIGRlZmluZWQgYXMgcG9wdWxhdGlvbiBiZWxvdyAxMF4yIGluIGJvdGggY2hhbm5lbHMgKGluIHRoZSBub2lzZSByYW5nZSkuCgpgYGB7cn0KI3NjUGFycyA8LSBnZ2N5dG9fcGFyX3NldChsaW1pdHMgPSBsaXN0KHggPSBjKDAsMWU2KSwgeSA9IGMoMCwxZTYpKSkKc2VsZWN0IDwtIGMoNywxOSkKZXggPC0gU3Vic2V0KGRhdFtzZWxlY3RdLCBzaW5nbGV0LmdhdGUpCnBvbHlnb24yIDwtIG1hdHJpeChjKDAsIDFlMiwgMWUyLCAwLAogICAgICAgICAgICAgICAgICAgIDAsIDAsIDFlMiwgMWUyKSwgbmNvbCA9IDIpCmNvbG5hbWVzKHBvbHlnb24yKSA8LSBjKCJCTDEuSCIsICJCTDMuSCIpCnVuc3RhaW5lZC5nYXRlIDwtIHBvbHlnb25HYXRlKGZpbHRlcklkID0gInVuc3RhaW5lZCIsIC5nYXRlID0gcG9seWdvbjIpCmdnY3l0byhleCwgYWVzKHggPSBCTDEuSCwgeSA9IEJMMy5IKSkgKwogIGdlb21faGV4KGJpbnMgPSA2NCkgKwogIGdlb21fZ2F0ZSh1bnN0YWluZWQuZ2F0ZSkgKyBnZW9tX3N0YXRzKCkgKyMgc2NQYXJzICsKICBzY2FsZV94X2xvZ2ljbGUoKSArIHNjYWxlX3lfbG9naWNsZSgpIApgYGAKQWRkIHRoaXMgZ2F0ZSB0byB0aGUgZ2F0aW5nU2V0CgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnc19wb3BfYWRkKGdzLCB1bnN0YWluZWQuZ2F0ZSwgcGFyZW50ID0gInNpbmdsZXQiLCBuYW1lID0gInVuc3RhaW5lZCIpCnJlY29tcHV0ZShncykKYGBgCgojIyBHYXRlIGZvciB0aGUgZGVhZC1saWtlIHBvcHVsYXRpb24KCj4gRGVhZCBwb3B1bGF0aW9uIGlzIGRlZmluZWQgYmFzZWQgb24gMU0gdHJlYXRlZCBzYW1wbGUuCgpgYGB7cn0KI3NjUGFycyA8LSBnZ2N5dG9fcGFyX3NldChsaW1pdHMgPSBsaXN0KHggPSBjKDAsMWU2KSwgeSA9IGMoMCwxZTYpKSkKc2VsZWN0IDwtIGMoMTksMjIpCmV4IDwtIFN1YnNldChkYXRbc2VsZWN0XSwgc2luZ2xldC5nYXRlKQojcG9seWdvbiA8LSBtYXRyaXgoYygxMF4zLCAxMF4yLjUsMTBeMywgMTBeNSwKIyAgICAgICAgICAgICAgICAgICAgMTBeNC41LCAxMF4yLjIsIDEwXjIuMiwgMTBeNCksIG5jb2wgPSAyKQpwb2x5Z29uIDwtIG1hdHJpeChjKDEwXjIsIDEwXjMsIDEwXjQuNSwgMTBeMi41LAogICAgICAgICAgICAgICAgICAgIDEwXjIuMywgMTBeMi4zLCAxMF40LCAxMF40KSwgbmNvbCA9IDIpCmNvbG5hbWVzKHBvbHlnb24pIDwtIGMoIkJMMS5IIiwgIkJMMy5IIikKZGVhZC5nYXRlIDwtIHBvbHlnb25HYXRlKGZpbHRlcklkID0gImRlYWRfbGlrZSIsIC5nYXRlID0gcG9seWdvbikKZ2djeXRvKGV4LCBhZXMoeCA9IEJMMS5ILCB5ID0gQkwzLkgpKSArCiAgZ2VvbV9oZXgoYmlucyA9IDY0KSArCiAgZ2VvbV9nYXRlKGRlYWQuZ2F0ZSkgKyBnZW9tX3N0YXRzKCkgKyAjc2NQYXJzICsKICBzY2FsZV94X2xvZ2ljbGUoKSArIHNjYWxlX3lfbG9naWNsZSgpIApgYGAKQWRkIHRoaXMgZ2F0ZSB0byB0aGUgZ2F0aW5nU2V0CgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnc19wb3BfYWRkKGdzLCBkZWFkLmdhdGUsIHBhcmVudCA9ICJzaW5nbGV0IiwgbmFtZSA9ICJkZWFkX2xpa2UiKQpyZWNvbXB1dGUoZ3MpCmBgYAoKCiMgQW5hbHlzaXMgJiBQbG90cwoKIyMgVmlzdWFsaXplIG9uZSBzZXQgb2YgZGF0YQpXaXRoIGdhdGVzCmBgYHtyfQpzdWJzZXQudG8ucGxvdCA8LSB3aXRoKHBEYXRhKGdzKSwgZHllID09ICJCb3RoIiAmIGRhdGUgPT0gJzIwMjQtMDEtMDknKQpwIDwtIGdnY3l0byhnc1tzdWJzZXQudG8ucGxvdF0sCiAgICAgICAgICAgIGFlcyh4ID0gQkwxLkgsIHkgPSBCTDMuSCksIHN1YnNldCA9ICJzaW5nbGV0IikgKyAKICBnZW9tX2hleChhZXMoZmlsbCA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLCBiaW5zID0gNjQpICsgCiAgZ2VvbV9nYXRlKCJkZWFkX2xpa2UiLCBsaW5ld2lkdGggPSAwLjUsIGFscGhhID0gMC41KSArCiAgZ2VvbV9zdGF0cyh0eXBlID0gInBlcmNlbnQiLCBsb2NhdGlvbiA9ICJnYXRlIiwgYWRqdXN0ID0gYygwLCAxKSwKICAgICAgICAgICAgIGRpZ2l0cyA9IDEsIHNpemUgPSAzKSArCiAgZ2VvbV9nYXRlKCJ1bnN0YWluZWQiLCBsaW5ld2lkdGggPSAwLjUsIGFscGhhID0gMC41KSArCiAgZ2VvbV9zdGF0cyh0eXBlID0gInBlcmNlbnQiLCBsb2NhdGlvbiA9ICJkYXRhIiwgYWRqdXN0ID0gYygwLjIsIDAuMDAzKSwKICAgICAgICAgICAgIGRpZ2l0cyA9IDEsIHNpemUgPSAzKSArCiAgZmFjZXRfZ3JpZChidWZmZXIgfiB0cmVhdG1lbnQsCiAgICAgICAgICAgICBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGModHIubGV2ZWxzLCBidS5sZXZlbHMpLCBtdWx0aV9saW5lID0gRikpICsKICBzY2FsZV94X2xvZ2ljbGUoYnJlYWtzID0gYygxMF4yLCAxMF4zLCAxMF40KSkgKyAKICBzY2FsZV95X2xvZ2ljbGUoYnJlYWtzID0gYygxMF4yLCAxMF4zLCAxMF40KSkgKyAKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArIAogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmF5MjAiKSArICNiYWNrZ3JvdW5kX2dyaWQobWFqb3IgPSAibm9uZSIsIG1pbm9yID0gIm5vbmUiKSArCiAgdGhlbWUoCiAgICAjYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAyKSwKICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjYpKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpCiAgKQpwcmludChwKQpnZ3NhdmUoIi4uL291dHB1dC9maWcyLWNvbXBhcmUtc3RhaW5pbmctYnVmZmVycy13aXRoLWdhdGUtMjAyNDA5MjMucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSA1KQpgYGAKV2l0aG91dCBnYXRlcwpgYGB7cn0Kc3Vic2V0LnRvLnBsb3QgPC0gd2l0aChwRGF0YShncyksIGR5ZSA9PSAiQm90aCIgJiBkYXRlID09ICcyMDI0LTAxLTA5JykKcCA8LSBnZ2N5dG8oZ3Nbc3Vic2V0LnRvLnBsb3RdLAogICAgICAgICAgICBhZXMoeCA9IEJMMS5ILCB5ID0gQkwzLkgpLCBzdWJzZXQgPSAic2luZ2xldCIpICsgCiAgZ2VvbV9oZXgoYWVzKGZpbGwgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwgYmlucyA9IDY0KSArIAogIGZhY2V0X2dyaWQoYnVmZmVyIH4gdHJlYXRtZW50LAogICAgICAgICAgICAgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKHRyLmxldmVscywgYnUubGV2ZWxzKSwgbXVsdGlfbGluZSA9IEYpKSArCiAgc2NhbGVfeF9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgc2NhbGVfeV9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKyAKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiZ3JheTIwIikgKyAjYmFja2dyb3VuZF9ncmlkKG1ham9yID0gIm5vbmUiLCBtaW5vciA9ICJub25lIikgKwogIHRoZW1lKAogICAgI2F4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gMiksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9IDIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC42KSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQogICkKcHJpbnQocCkKZ2dzYXZlKCIuLi9vdXRwdXQvZmlnMi1jb21wYXJlLXN0YWluaW5nLWJ1ZmZlcnMtbm8tZ2F0ZS0yMDI0MDkyMy5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDUpCmBgYApgYGB7cn0KCmBgYAojIyBFeHBvcnQgZ2F0ZWQgZXZlbnQgY291bnRzCgpgYGB7cn0KdG1wIDwtIGdzX3BvcF9nZXRfc3RhdHMoZ3MpICU+JSAKICBtdXRhdGUocG9wID0gZ3N1YigiLiovIiwgIiIsIHBvcCksIHBvcCA9IGdzdWIoIi1vdXRsaWVyIiwgImNlbGxzIiwgcG9wKSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwb3AsIG5hbWVzX3ByZWZpeCA9ICJuXyIsIHZhbHVlc19mcm9tID0gY291bnQpICU+JSAKICBtdXRhdGUoCiAgICBwY19kZWFkX2xpa2UgPSBudW0obl9kZWFkX2xpa2UgLyBuX3NpbmdsZXQsIGxhYmVsID0gIiUiLCBzY2FsZSA9IDEwMCksCiAgICBwY191bnN0YWluZWQgPSBudW0obl91bnN0YWluZWQgLyBuX3NpbmdsZXQsIGxhYmVsID0gIiUiLCBzY2FsZSA9IDEwMCkKICApCgpnYXRlZF9zdGF0cyA8LSBsZWZ0X2pvaW4oCiAgYXNfdGliYmxlKHBEYXRhKGdzKSksCiAgdG1wLAogIGJ5ID0gYygibmFtZSIgPSAic2FtcGxlIikKKSAlPiUgZHBseXI6OmZpbHRlcihkeWUgPT0gIkJvdGgiKSAlPiUgc2VsZWN0KC1keWUpCiAgCnByaW50KGdhdGVkX3N0YXRzKQp3cml0ZV90c3YoZ2F0ZWRfc3RhdHMsIGZpbGUgPSAiLi4vb3V0cHV0L2ZpZzItY29tcGFyZS1zdGFpbmluZy1idWZmZXItZ2F0ZWQtc3RhdHMudHN2IikKYGBgCgojIyBQbG90IHBlcmNlbnRhZ2VzCldlIHdpbGwgcHJpbWFyaWx5IGxvb2sgYXQgdGhlIG1vY2sgc2FtcGxlLCBhcyB0aGUgcHVycG9zZSBvZiB0aGUgYnVmZmVyIGNvbXBhcmlzb24gaXMgdG8gZmluZCBhIGJ1ZmZlciB0aGF0IHdpbGwgbWluaW1pemUgdGhlIGRlYWQtbGlrZSBhbmQgdW5zdGFpbmVkIHBvcHVsYXRpb25zLgpgYGB7cn0KcDEgPC0gZ2F0ZWRfc3RhdHMgJT4lIAogICMgcGxvdCB0aGUgbW9jayBzYW1wbGUgb25seQogIGRwbHlyOjpmaWx0ZXIodHJlYXRtZW50ID09ICIwIikgJT4lIAogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBzdGFydHNfd2l0aCgicGNfIiksCiAgICBuYW1lc190byA9ICJ2YXIiLAogICAgdmFsdWVzX3RvID0gInZhbHVlIgogICkgJT4lIAogIGdncGxvdChhZXMoeCA9IGJ1ZmZlciwgeSA9IHZhbHVlKSkgICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLCBmaWxsID0gImdyYXk4MCIpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjA1KSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBidS5sZXZlbHMpICsKICBmYWNldF93cmFwKH52YXIsIG5yb3cgPSAyLCBzY2FsZXMgPSAiZnJlZV95IiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcigKICAgIGMoInBjX2RlYWRfbGlrZSIgPSAiJSBEZWFkLWxpa2UiLCAicGNfdW5zdGFpbmVkIiA9ICIlIFVuc3RhaW5lZCIpKSkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiUG9wdWxhdGlvbiBmcmVxdWVuY3kiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxOCkgKyBwYW5lbF9ib3JkZXIoY29sb3IgPSAiZ3JheTIwIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJzdGVlbGJsdWUiLCBmYWNlID0gMikpCnByaW50KHAxICsgZmFjZXRfd3JhcCh+dmFyLCBuY29sID0gMiwgc2NhbGVzID0gImZyZWVfeSIsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoCiAgICBjKCJwY19kZWFkX2xpa2UiID0gIiUgRGVhZC1saWtlIiwgInBjX3Vuc3RhaW5lZCIgPSAiJSBVbnN0YWluZWQiKSkpKQpnZ3NhdmUoZmlsZW5hbWUgPSAiLi4vb3V0cHV0L2ZpZzJiYy1jb21wYXJlLWJ1ZmZlci1wbG90LXN0YXRzLnBuZyIsIAogICAgICAgcGxvdCA9IHAxLCB3aWR0aCA9IDQsIGhlaWdodCA9IDcpCmBgYAojIyBTYW1wbGUtdG8tc2FtcGxlIHZhcmlhdGlvbgpWaXNhdWxpemUgc2FtcGxlLXRvLXNhbXBsZSB2YXJpYWJpbGl0eSBpbiBtb2NrLXRyZWF0ZWQgY2VsbHMgYWNyb3NzIHRocmVlIHJlcGxpY2F0ZXMKYGBge3J9CnN1YnNldC50by5wbG90IDwtIHdpdGgocERhdGEoZ3MpLCBkeWUgPT0gIkJvdGgiICYgdHJlYXRtZW50ID09ICIwIikKZGF0ZS5sZXZlbHMgPSBwYXN0ZSgiUmVwbGljYXRlIiwgMTozKTsgbmFtZXMoZGF0ZS5sZXZlbHMpID0gdW5pcXVlKHNhbXBsZSRkYXRlKQpwIDwtIGdnY3l0byhnc1tzdWJzZXQudG8ucGxvdF0sCiAgICAgICAgICAgIGFlcyh4ID0gQkwxLkgsIHkgPSBCTDMuSCksIHN1YnNldCA9ICJzaW5nbGV0IikgKyAKICBnZW9tX2hleChhZXMoZmlsbCA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLCBiaW5zID0gNjQpICsgCiAgZmFjZXRfZ3JpZChkYXRlfmJ1ZmZlciwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKGRhdGUubGV2ZWxzLCBidS5sZXZlbHMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlfbGluZSA9IEYpKSArCiAgc2NhbGVfeF9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgc2NhbGVfeV9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKyAKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiZ3JheTIwIikgKyAjYmFja2dyb3VuZF9ncmlkKG1ham9yID0gIm5vbmUiLCBtaW5vciA9ICJub25lIikgKwogIHRoZW1lKAogICAgI2F4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gMiksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9IDIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC42KSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQogICkKcHJpbnQocCkKYGBgCgojIyBTdXBwbGVtZW50YXJ5IHBsb3RzClBJLWFsb25lCmBgYHtyfQpzdWJzZXQudG8ucGxvdCA8LSB3aXRoKHBEYXRhKGdzKSwgZHllID09ICJQSSIgJiBkYXRlID09ICcyMDI0LTAxLTA5JykKcCA8LSBnZ2N5dG8oZ3Nbc3Vic2V0LnRvLnBsb3RdLAogICAgICAgICAgICBhZXMoeCA9IEJMMS5ILCB5ID0gQkwzLkgpLCBzdWJzZXQgPSAic2luZ2xldCIpICsgCiAgZ2VvbV9oZXgoYWVzKGZpbGwgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwgYmlucyA9IDY0KSArIAogIGZhY2V0X2dyaWQoYnVmZmVyIH4gdHJlYXRtZW50LAogICAgICAgICAgICAgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKHRyLmxldmVscywgYnUubGV2ZWxzKSwgbXVsdGlfbGluZSA9IEYpKSArCiAgc2NhbGVfeF9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgc2NhbGVfeV9sb2dpY2xlKGJyZWFrcyA9IGMoMTBeMiwgMTBeMywgMTBeNCkpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKyAKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiZ3JheTIwIikgKyAjYmFja2dyb3VuZF9ncmlkKG1ham9yID0gIm5vbmUiLCBtaW5vciA9ICJub25lIikgKwogIHRoZW1lKAogICAgI2F4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gMiksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9IDIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC42KSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQogICkKcHJpbnQocCkKZ2dzYXZlKCIuLi9vdXRwdXQvZmlnMnN1cC1jb21wYXJlLXN0YWluaW5nLWJ1ZmZlcnMtUEktb25seS0yMDI0MDkyMy5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDUpCmBgYApTWVRPOSBhbG9uZQpgYGB7cn0Kc3Vic2V0LnRvLnBsb3QgPC0gd2l0aChwRGF0YShncyksIGR5ZSA9PSAiU1lUTzkiICYgZGF0ZSA9PSAnMjAyNC0wMS0wOScpCnAgPC0gZ2djeXRvKGdzW3N1YnNldC50by5wbG90XSwKICAgICAgICAgICAgYWVzKHggPSBCTDEuSCwgeSA9IEJMMy5IKSwgc3Vic2V0ID0gInNpbmdsZXQiKSArIAogIGdlb21faGV4KGFlcyhmaWxsID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksIGJpbnMgPSAxMjgpICsgCiAgZmFjZXRfZ3JpZChidWZmZXIgfiB0cmVhdG1lbnQsCiAgICAgICAgICAgICBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGModHIubGV2ZWxzLCBidS5sZXZlbHMpLCBtdWx0aV9saW5lID0gRikpICsKICBzY2FsZV94X2xvZ2ljbGUoYnJlYWtzID0gYygxMF4yLCAxMF4zLCAxMF40KSkgKyAKICBzY2FsZV95X2xvZ2ljbGUoYnJlYWtzID0gYygxMF4yLCAxMF4zLCAxMF40KSkgKyAKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArIAogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmF5MjAiKSArICNiYWNrZ3JvdW5kX2dyaWQobWFqb3IgPSAibm9uZSIsIG1pbm9yID0gIm5vbmUiKSArCiAgdGhlbWUoCiAgICAjYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAyKSwKICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjYpKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpCiAgKQpwcmludChwKQpnZ3NhdmUoIi4uL291dHB1dC9maWcyc3VwLWNvbXBhcmUtc3RhaW5pbmctYnVmZmVycy1TWVRPOS1vbmx5LTIwMjQwOTIzLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSkKYGBgCgoKCgo=